﻿/*  
    Copyright (C) <2007-2013>  <Kay Diefenthal>

    ArgusTv.UI.MediaCenter is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ArgusTv.UI.MediaCenter is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ArgusTv.UI.MediaCenter.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using ArgusTV.DataContracts;
using ArgusTV.ServiceAgents;
using ArgusTV.UI.MediaCenter.Logging;
using ArgusTV.UI.MediaCenter.Models;
using ArgusTV.UI.MediaCenter.Views;
using Microsoft.MediaCenter;
using Microsoft.MediaCenter.Hosting;
using Microsoft.MediaCenter.UI;

namespace ArgusTV.UI.MediaCenter.ViewModels
{
    public class SearchModel : ModelItem
    {
        #region Private Fields

        private readonly ChannelType _channelType;
        private readonly AddInHost _host;
        private readonly HistoryOrientedPageSession _session;

        #endregion

        #region Constructor

        /// <summary>
        /// SearchModel Initialize a new Instance of <see cref="SearchModel"/> Class.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="host"></param>
        /// <param name="type"></param>
        public SearchModel(HistoryOrientedPageSession session, AddInHost host, Int32 type)
        {
            _session = session;
            _host = host;
            _channelType = (ChannelType) type;
        }

        #endregion

        #region Properties

        /// <summary>
        /// MediaCenterEnvironment
        /// </summary>
        public MediaCenterEnvironment MediaCenterEnvironment
        {
            get
            {
                if (_host == null) return null;
                return _host.MediaCenterEnvironment;
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// CreateSearchOptionsView Initialize a new Instance of <see cref="SearchOptionsView"/> Class.
        /// </summary>
        /// <returns></returns>
        private SearchOptionsView CreateSearchOptionsView()
        {
            try
            {
                var view = new SearchOptionsView();
                view.Commands = new ArrayListDataSet(view);
                CreateSearchOptionsCommand(view, Resources.SearchOptionsTypeTitleDescription,
                                           ScheduleRuleType.TitleContains);
                CreateSearchOptionsCommand(view, Resources.SearchOptionsTypeKeywordDescription,
                                           ScheduleRuleType.DescriptionContains);
                CreateSearchOptionsCommand(view, Resources.SearchOptionsTypeCategoriesDescription,
                                           ScheduleRuleType.CategoryEquals);
                CreateSearchOptionsCommand(view, Resources.SearchOptionsTypeActorsDescription,
                                           ScheduleRuleType.WithActor);
                CreateSearchOptionsCommand(view, Resources.SearchOptionsTypeDirectorsDescription,
                                           ScheduleRuleType.DirectedBy);
                return view;
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "CreateSearchOptionsView", exception));
                return null;
            }

        }

        /// <summary>
        /// CreateSearchOptionsCommand
        /// </summary>
        /// <param name="view"></param>
        /// <param name="description"></param>
        /// <param name="type"></param>
        private void CreateSearchOptionsCommand(SearchOptionsView view, String description, ScheduleRuleType type)
        {
            try
            {
                var command = new SearchOptionsCommand(view, description, type);
                command.Invoked += (sender, e) => OnSearchOptionsCommandInvoked((SearchOptionsCommand) sender);
                view.Commands.Add(command);
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "CreateSearchOptionsCommand",
                                           exception));
            }

        }

        /// <summary>
        /// OnSearchOptionsCommandInvoked
        /// </summary>
        /// <param name="command"></param>
        private void OnSearchOptionsCommandInvoked(SearchOptionsCommand command)
        {
            try
            {
                var searchView = CreateSearchView(command.Type);
                GoToSearchView(searchView);
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "OnSearchOptionsCommandInvoked",
                                           exception));
            }

        }

        /// <summary>
        /// CreateSearchView Initialize a new Instance of <see cref="SearchView"/> Class.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private SearchView CreateSearchView(ScheduleRuleType type)
        {
            try
            {
                var view = new SearchView();
                var contentList = new VirtualList(view, null) {EnableSlowDataRequests = true};
                view.Content = contentList;
                view.SearchTerm = new EditableText();
                view.SearchTermChanged += delegate { CreateSearchViewContent(view, type, view.SearchTerm.Value); };
                return view;
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "CreateSearchView", exception));
                return null;
            }

        }

        /// <summary>
        /// CreateSearchViewContent
        /// </summary>
        /// <param name="view"></param>
        /// <param name="type"></param>
        /// <param name="term"></param>
        private void CreateSearchViewContent(SearchView view, ScheduleRuleType type, String term)
        {
            try
            {
                view.Content.Clear();
                switch (type)
                {
                    case ScheduleRuleType.TitleContains:
                        using (var schedulerServiceAgent = new SchedulerServiceAgent())
                        {
                            var schedule = new Schedule {ChannelType = _channelType};
                            //schedule.ChannelType = _channelType;
                            schedule.Rules.Add(ScheduleRuleType.TitleContains, term);
                            var upcomingprograms = schedulerServiceAgent.GetUpcomingPrograms(schedule, false);
                            if (upcomingprograms.Length == 0)
                            {
                            }
                            foreach (var t in upcomingprograms)
                            {
                                view.Content.Add(CreateSearchCommand(t));
                            }
                        }
                        break;
                    case ScheduleRuleType.DescriptionContains:
                        using (var schedulerServiceAgent = new SchedulerServiceAgent())
                        {
                            var schedule = new Schedule {ChannelType = _channelType};
                            schedule.Rules.Add(ScheduleRuleType.DescriptionContains, term);
                            schedule.Rules.Add(ScheduleRuleType.ProgramInfoContains, term);
                            var upcomingprograms = schedulerServiceAgent.GetUpcomingPrograms(schedule, false);
                            if (upcomingprograms.Length == 0)
                            {
                            }
                            foreach (var t in upcomingprograms)
                            {
                                view.Content.Add(CreateSearchCommand(t));
                            }
                        }
                        break;
                    case ScheduleRuleType.CategoryEquals:
                        using (var schedulerServiceAgent = new SchedulerServiceAgent())
                        {
                            var schedule = new Schedule {ChannelType = _channelType};
                            schedule.Rules.Add(ScheduleRuleType.CategoryEquals, term);
                            var upcomingprograms = schedulerServiceAgent.GetUpcomingPrograms(schedule, false);
                            if (upcomingprograms.Length == 0)
                            {
                            }
                            foreach (var t in upcomingprograms)
                            {
                                view.Content.Add(CreateSearchCommand(t));
                            }
                        }
                        break;
                    case ScheduleRuleType.WithActor:
                        using (var schedulerServiceAgent = new SchedulerServiceAgent())
                        {
                            var schedule = new Schedule {ChannelType = _channelType};
                            schedule.Rules.Add(ScheduleRuleType.WithActor, term);
                            var upcomingprograms = schedulerServiceAgent.GetUpcomingPrograms(schedule, false);
                            if (upcomingprograms.Length == 0)
                            {
                            }
                            foreach (var t in upcomingprograms)
                            {
                                view.Content.Add(CreateSearchCommand(t));
                            }
                        }
                        break;
                    case ScheduleRuleType.DirectedBy:
                        using (var schedulerServiceAgent = new SchedulerServiceAgent())
                        {
                            var schedule = new Schedule {ChannelType = _channelType};
                            schedule.Rules.Add(ScheduleRuleType.DirectedBy, term);
                            var upcomingprograms = schedulerServiceAgent.GetUpcomingPrograms(schedule, false);
                            if (upcomingprograms.Length == 0)
                            {
                            }
                            foreach (var t in upcomingprograms)
                            {
                                view.Content.Add(CreateSearchCommand(t));
                            }
                        }
                        break;
                }
                view.FocusChanged += delegate(object sender, EventArgs args)
                    {
                        var searchItem = (SearchCommand) sender;
                        var guideProgramId = searchItem.Upcoming.GuideProgramId;
                        using (var guideserviceAgent = new GuideServiceAgent())
                        {
                            if (guideProgramId != null)
                            {
                                var program = guideserviceAgent.GetProgramById(guideProgramId.Value);
                                view.Info = new OnDemandOfferModel(program);
                            }
                        }
                    };

            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "CreateSearchViewContent", exception));
            }
        }

        /// <summary>
        /// CreateSearchCommand Initialize a new Instance of <see cref="SearchCommand"/> Class.
        /// </summary>
        /// <param name="upcoming"></param>
        /// <returns></returns>
        private SearchCommand CreateSearchCommand(UpcomingProgram upcoming)
        {
            try
            {
                var item = new SearchCommand
                    {
                        Description = upcoming.Title,
                        UniqueId = upcoming.UpcomingProgramId,
                        Upcoming = upcoming
                    };
                item.Invoked += delegate(object sender, EventArgs args)
                    {
                        var searchItem = (SearchCommand) sender;
                        var detailsView = CreateSearchDetailsView(searchItem.Upcoming);
                        GoToDetailsView(detailsView);
                    };
                return item;
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "CreateSearchCommand", exception));
                return null;
            }

        }

        /// <summary>
        /// CreateSearchDetailsView Initialize a new Instance of <see cref="DetailsView"/> Class.
        /// </summary>
        /// <param name="upcomingprogram"></param>
        /// <returns></returns>
        private DetailsView CreateSearchDetailsView(UpcomingProgram upcomingprogram)
        {
            try
            {
                var view = new DetailsView
                    {
                        Title = upcomingprogram.Title + " : " + upcomingprogram.SubTitle,
                        Summary = String.Format("{0}{1}{2}{3}{4}{5}{6}", upcomingprogram.Channel.DisplayName, ", ",
                                                upcomingprogram.StartTime.ToShortDateString(), " ",
                                                upcomingprogram.StartTime.ToShortTimeString(), " - ",
                                                upcomingprogram.StopTime.ToShortTimeString())
                    };
                using (var guideserviceAgent = new GuideServiceAgent())
                {
                    if (upcomingprogram.GuideProgramId != null)
                    {
                        GuideProgram program = guideserviceAgent.GetProgramById(upcomingprogram.GuideProgramId.Value);
                        view.Metadata = program.Description;
                    }
                }
                view.Commands = new ArrayListDataSet(view);
                CreateSearchDetailCommands(view, Resources.RecordDescription, DetailsCommandTypes.RecordAnyTime,
                                           upcomingprogram, "res://ehres!DETAILS.CMD.RECORDSERIES.DORMANT.PNG",
                                           "res://ehres!DETAILS.CMD.RECORDSERIES.FOCUS.PNG",
                                           "res://ehres!DETAILS.CMD.RECORDSERIES.PNG");
                return view;
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "CreateSearchDetailsView", exception));
                return null;
            }

        }

        /// <summary>
        /// CreateSearchDetailCommands
        /// </summary>
        /// <param name="view"></param>
        /// <param name="description"></param>
        /// <param name="type"></param>
        /// <param name="upcomingprogram"></param>
        /// <param name="dormant"></param>
        /// <param name="focus"></param>
        /// <param name="nofocus"></param>
        private void CreateSearchDetailCommands(DetailsView view, String description, DetailsCommandTypes type,
                                                UpcomingProgram upcomingprogram, String dormant, String focus,
                                                String nofocus)
        {
            try
            {
                var command = new DetailsCommand(view, description, type, upcomingprogram)
                    {
                        Dormant = new Image(dormant),
                        Focus = new Image(focus),
                        NoFocus = new Image(nofocus)
                    };
                command.Invoked += (sender, e) => OnDetailCommandInvoked((DetailsCommand) sender, upcomingprogram);
                view.Commands.Add(command);
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "CreateSearchDetailCommands",
                                           exception));
            }

        }

        /// <summary>
        /// OnDetailCommandInvoked
        /// </summary>
        /// <param name="command"></param>
        /// <param name="upcomingprogram"></param>
        private void OnDetailCommandInvoked(DetailsCommand command, UpcomingProgram upcomingprogram)
        {
            try
            {
                switch (command.Type)
                {
                    case DetailsCommandTypes.RecordAnyTime:
                        using (var schedulerServiceAgent = new SchedulerServiceAgent())
                        {
                            Schedule schedule =
                                schedulerServiceAgent.CreateNewSchedule(upcomingprogram.Channel.ChannelType,
                                                                        ScheduleType.Recording);
                            schedule.Name = upcomingprogram.Title;
                            schedule.Rules.Add(ScheduleRuleType.Channels, upcomingprogram.Channel.ChannelId);
                            schedule.Rules.Add(ScheduleRuleType.ManualSchedule, upcomingprogram.StartTime,
                                               new ScheduleTime(upcomingprogram.Duration));
                            schedulerServiceAgent.SaveSchedule(schedule);
                        }
                        break;
                }
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "OnDetailCommandInvoked", exception));
            }
        }

        /// <summary>
        /// Navigate to SearchView
        /// </summary>
        /// <param name="view"></param>
        private void GoToSearchView(SearchView view)
        {
            try
            {
                var uiProperties = new Dictionary<string, object>();
                uiProperties["SearchView"] = view;
                _session.GoToPage("resx://ArgusTV.UI.MediaCenter/ArgusTV.UI.MediaCenter.Resources/SearchView",
                                  uiProperties);
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "GoToSearchView", exception));
            }
        }

        /// <summary>
        /// Navigate to DetailsView
        /// </summary>
        /// <param name="view"></param>
        private void GoToDetailsView(DetailsView view)
        {
            try
            {
                var uiProperties = new Dictionary<string, object>();
                uiProperties["DetailsView"] = view;
                _session.GoToPage("resx://ArgusTV.UI.MediaCenter/ArgusTV.UI.MediaCenter.Resources/DetailsView",
                                  uiProperties);
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "GoToDetailsView", exception));
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Navigate to SearchOptionsView
        /// </summary>
        public void GoToSearchOptionsView()
        {
            try
            {
                var uiProperties = new Dictionary<string, object>();
                uiProperties["SearchOptionsView"] = CreateSearchOptionsView();
                _session.GoToPage("resx://ArgusTV.UI.MediaCenter/ArgusTV.UI.MediaCenter.Resources/SearchOptionsView",
                                  uiProperties);
            }
            catch (Exception exception)
            {
                Logger.Error(string.Format("{0}{1}:{2}", "SearchOptionsViewModel", "GoToSearchOptionsView", exception));
            }
        }

        #endregion
    }
}